﻿using System.Collections.Generic;
using DigitalQuran.Statistic;
using System;

namespace DigitalQuran.Numerology.Systems {

    class Linear : NumerologySystem {
        public override IEnumerator<long> GetValues() {
            long l = 1;
            for (; ; ) {
                yield return l++;
            }
        }
    }

    class Odd : NumerologySystem {

        public override IEnumerator<long> GetValues() {
            long l = 1;
            for (; ; ) {
                yield return l;
                l += 2;
            }
        }
    }

    class Even : NumerologySystem {

        public override IEnumerator<long> GetValues() {
            long l = 0;
            for (; ; ) {
                yield return l;
                l += 2;
            }
        }
    }

    class Prime : NumerologySystem {
        internal Prime(bool includeOne) {
            if (includeOne)
                i = 0;            
        }
        int i = 1;

        public override IEnumerator<long> GetValues() {
            for (; i < Numbers.Primes.Length; i++) {
                yield return Numbers.Primes[i];
            }
        }
    }

    class AdditivePrimes : NumerologySystem {
        internal AdditivePrimes(bool includeOne) {
            if (includeOne)
                i = 0;
        }
        int i = 1;

        public override IEnumerator<long> GetValues() {
            for (; i < Numbers.AdditivePrimes.Length; i++)
                yield return Numbers.AdditivePrimes[i];            
        }
    }

    class PurePrimes : NumerologySystem {
        internal PurePrimes(bool includeOne) {
            if (includeOne)
                i = 0;
        }
        int i = 1;

        public override IEnumerator<long> GetValues() {
            for (; i < Numbers.PurePrimes.Length; i++)
                yield return Numbers.PurePrimes[i];
        }
    }

    class MersennePrimes : NumerologySystem {

        public override IEnumerator<long> GetValues() {
            for (int i = 0; i < Numbers.MersennePrimes.Length; i++)
                yield return Numbers.MersennePrimes[i];
        }
    }

    class Composite : NumerologySystem {

        public override IEnumerator<long> GetValues() {
            for (int i = 0; i < Numbers.Composites.Length; i++)
                yield return Numbers.Composites[i];
        }
    }

    class AdditiveComposite : NumerologySystem {

        public override IEnumerator<long> GetValues() {
            for (int i = 0; i < Numbers.AdditiveComposites.Length; i++)
                yield return Numbers.AdditiveComposites[i];
        }
    }

    class PureComposite : NumerologySystem {

        public override IEnumerator<long> GetValues() {
            for (int i = 0; i < Numbers.PureComposites.Length; i++)
                yield return Numbers.PureComposites[i];
        }
    }

    class Fibonaccis : NumerologySystem {

        public override IEnumerator<long> GetValues() {
            for (int i = 0; i < Numbers.Fibonaccis.Count; i++)
                yield return Numbers.Fibonaccis[i];
        }
    }

    class FrequencyAsending : NumerologySystem {
        internal override void Update(LetterStatisticTable stat, string textMode) {
            base.Update(stat, textMode);

            stat.Sort(SortMethod.ByFrequency, SortOrder.Ascending);
            int i = 0;
            foreach (var item in this) {
                this[item.Key] = stat[i++].Frequency;
            }
        }

        public override IEnumerator<long> GetValues() {
            yield return 0;
        }
    }

    class FrequencyDesending : NumerologySystem {
        internal override void Update(LetterStatisticTable stat, string textMode) {
            base.Update(stat, textMode);

            stat.Sort(SortMethod.ByFrequency, SortOrder.Descending);
            int i = 0;
            foreach (var item in this) {
                this[item.Key] = stat[i++].Frequency;
            }
        }

        public override IEnumerator<long> GetValues() {
            yield return 0;
        }
    }

    class Log2 : NumerologySystem {
        
        public override IEnumerator<long> GetValues() {
            for (int i = 0; i < Numbers.Log2s.Count; i++)
                yield return Numbers.Log2s[i];            
        }
    }

    class Log10 : NumerologySystem {

        public override IEnumerator<long> GetValues() {
            for (int i = 0; i < Numbers.Log10s.Count; i++)
                yield return Numbers.Log10s[i];
        }
    }

    class PivotBook : NumerologySystem {

        public override IEnumerator<long> GetValues() {

            var pivots = Polygon.Pivots(PivotType.Book);
            foreach (var p in pivots) {
                yield return p;
            }
        }
    }

    class PivotChapter : NumerologySystem {

        public override IEnumerator<long> GetValues() {
            var pivots = Polygon.Pivots(PivotType.Chapter);
            foreach (var p in pivots) {
                yield return p;
            }
        }
    }

    class PivotChapterFirstFactors : NumerologySystem {

        public override IEnumerator<long> GetValues() {
            var pivots = Polygon.Pivots(PivotType.ChapterFirstFactors);
            foreach (var p in pivots) {
                yield return p;
            }
        }
    }

    class PivotChapterSecondFactors : NumerologySystem {

        public override IEnumerator<long> GetValues() {
            var pivots = Polygon.Pivots(PivotType.ChapterSecondFactors);
            foreach (var p in pivots) {
                yield return p;
            }
        }
    }

    class PivotChapterVerses : NumerologySystem {

        public override IEnumerator<long> GetValues() {
            var pivots = Polygon.Pivots(PivotType.ChapterVerses);
            foreach (var p in pivots) {
                yield return p;
            }
        }
    }

    class PivotSupportChapters : NumerologySystem {

        public override IEnumerator<long> GetValues() {
            var pivots = Polygon.Pivots(PivotType.SupportChapters);
            foreach (var p in pivots) {
                yield return p;
            }
        }
    }

    class Polygons : NumerologySystem {
        internal Polygons(byte sides) {
            n = Convert.ToUInt32(sides);
        }
        uint n;

        public override IEnumerator<long> GetValues() {
            var p = Polygon.PolygonNumbers(n);

            foreach (var i in p) {
                yield return (long)i;
            }
        }
    }

    class CenteredPolygons : NumerologySystem {
        internal CenteredPolygons(byte sides) {
            n = Convert.ToUInt32(sides);
        }
        uint n;

        public override IEnumerator<long> GetValues() {
            var p = Polygon.CenteredPolygonNumbers(n);

            foreach (var i in p) {
                yield return (long)i;
            }
        }
    }

    class PolyhexNumbers : NumerologySystem {
        internal PolyhexNumbers(byte number) {
            n = Convert.ToUInt32(number);
        }
        uint n;

        public override IEnumerator<long> GetValues() {
            var p = Polygon.PolyhexNumbers(n);

            foreach (var i in p) {
                yield return (long)i;
            }
        }
    }

    class Tetahedrals : NumerologySystem {

        public override IEnumerator<long> GetValues() {
            foreach (var p in Polygon.Tetrahedrals) {
                yield return p;
            }
        }
    }

    class Pyramidals : NumerologySystem {

        public override IEnumerator<long> GetValues() {
            foreach (var p in Polygon.Pyramidals) {
                yield return p;
            }
        }
    }

    class Cubics : NumerologySystem {

        public override IEnumerator<long> GetValues() {
            foreach (var p in Polygon.Cubics) {
                yield return p;
            }
        }
    }
}